﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Text;

using stdole;
using Office = Microsoft.Office.Core;
using Microsoft.Office.Core;

using SharpSvn;

using OfficeSVN.Properties;


namespace OfficeSVN {

    /// <summary>
    /// todo
    /// </summary>
    /// <example>
    /// 
    /// </example>
    /// <remarks>
    /// Open Defects:
    /// 
    /// Excel: Strg+S -> Kein Ribbon-Update
    /// Excel: Unterschiedliche Revsion bei GetLock/ReleaseLock
    /// Office: Anzeige im Ribbon, ob neuere Version verfügbar
    /// </remarks>
    [ComVisible(true)]
    public sealed class OfficeSvnRibbon : IOfficeSVNRibbon
    {
        private Office.IRibbonUI _ribbon;
        private SubversionFileInfo _fileInfo;
        private string _currentDocument;

        public event EventHandler<RibbonButtonEventArgs> ButtonClicked;

        public event EventHandler<DocumentEventArgs> DocumentSaved;

        public string GetCustomUI(string ribbonId) {

            Assembly executingAssembly = Assembly.GetExecutingAssembly();
            IEnumerable<string> resourceNames = executingAssembly.GetManifestResourceNames();

            return (from resourceName in resourceNames
                    where resourceName.EndsWith("OfficeSVNRibbon.xml")
                    select ReadRessource(executingAssembly, resourceName)).FirstOrDefault();
        }

        private static string ReadRessource(Assembly assembly, string resourceName)
        {
            using (StreamReader resourceReader = new StreamReader(assembly.GetManifestResourceStream(resourceName))) {
                return resourceReader.ReadToEnd();
            }
        }

        public void Ribbon_Load(Office.IRibbonUI ribbonUI) {
            this._ribbon = ribbonUI;
        }

        public void ButtonClick(IRibbonControl control) {

            using (new MousePointer())
            {
                // string Path = this.CurrentDocument;

                this.OnButtonClickedEvent(control.Id);
            }
        }

        public string GetLabel(IRibbonControl control) {

            using (new MousePointer()) {

                SubversionFileInfo info = _fileInfo;

                switch (control.Id) {
                    case "repositoryPathLabel":
                        return info.RepositoryPath.ToString();

                    case "revisionLabel":
                        return info.Revision.ToString();

                    case "statusLabel":
                        // Replace "zero" with empty string (looks better)
                        return (info.Status == SvnStatus.Zero) ? "" : info.Status.ToString();
                }

                return "default-label";
            }
        }

        public bool GetEnabled(IRibbonControl control) {

            using (new MousePointer()) {

                switch (control.Id) {
                    case "getLockButton":
                        return (_fileInfo.Status == SvnStatus.Normal || _fileInfo.Status == SvnStatus.None) && (_fileInfo.NeedsLock && !_fileInfo.IsLocked);

                    case "releaseLockButton":
                        return (_fileInfo.Status == SvnStatus.Normal || _fileInfo.Status == SvnStatus.None) && (_fileInfo.NeedsLock && _fileInfo.IsLocked);

                    case "addButton":
                        return (_fileInfo.Status == SvnStatus.NotVersioned);

                    case "revertButton":
                        return (_fileInfo.Status == SvnStatus.Added || _fileInfo.Status == SvnStatus.Modified);

                    case "commentEditBox":
                        return (_fileInfo.Status == SvnStatus.Added || _fileInfo.Status == SvnStatus.Modified);

                    case "commitButton":
                        return (_fileInfo.Status == SvnStatus.Added || _fileInfo.Status == SvnStatus.Modified);

                    case "updateButton":
                        return (_fileInfo.Status == SvnStatus.Normal || _fileInfo.Status == SvnStatus.None);
                }

                return false;
            }
        }

        public IPictureDisp GetImageCallback(string imageName) {

            object resourceImage = Resources.ResourceManager.GetObject(imageName);

            if (resourceImage == null) {
                MessageBox.Show(String.Format("Could not find the resource for image name '{0}'.", imageName), "OfficeSVN", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return null;
            }

            return PictureConverter.ImageToPictureDisp((Image)resourceImage);
        }

        /// <summary>
        /// Updates the enabled status of the commands on the OfficeSVN ribbon.
        /// </summary>
        /// <remarks>
        /// This method has to be called after
        ///     - opening a document 
        ///     - saving a document
        ///     - switching between the documents 
        /// </remarks>
        /// <param name="fileInfo"></param>
        public void UpdateRibbon(string document, SubversionFileInfo fileInfo)
        {
            _currentDocument = document;
            _fileInfo = fileInfo;

            // Causes all of your custom controls to re-initialize.
            _ribbon.Invalidate();
        }

        private void OnDocumentSavedEvent(string document)
        {
            // Copy to a temporary variable to be thread-safe.
            EventHandler<DocumentEventArgs> temp = DocumentSaved;
            if (temp != null)
                temp(null, new DocumentEventArgs(document));
        }

        //private void OnDocumentOpenedEvent(string document) {
        //    // Copy to a temporary variable to be thread-safe.
        //    EventHandler<DocumentEventArgs> temp = DocumentOpened;
        //    if (temp != null)
        //        temp(null, new DocumentEventArgs(document));
        //}
        //private void OnDocumentClosedEvent(string document)
        //{
        //    // Copy to a temporary variable to be thread-safe.
        //    EventHandler<DocumentEventArgs> temp = DocumentClosed;
        //    if (temp != null)
        //        temp(null, new DocumentEventArgs(document));
        //}

        public void OfficeSvnFileSave(IRibbonControl control, bool cancelDefault)
        {
            // 1) Save the document
            // SaveDocument(path);

            // 2) Inform controller about the saved document
            OnDocumentSavedEvent(_currentDocument);
        }

        private void OnButtonClickedEvent(string buttonId)
        {
            EventHandler<RibbonButtonEventArgs> temp = ButtonClicked;
            if (temp != null) 
                temp(null, new RibbonButtonEventArgs(buttonId));
        }
    }
}
